﻿using System;
using System.Collections.Generic;
using System.Text;
using global::ExpressionUtil.Common;

namespace ExpressionUtil.Parser
{
    /// <summary>
    /// 表达式扫描器
    /// </summary>
    internal class ExpressionScanner
    {
        /// <summary>
        /// 需要扫描的字符串
        /// </summary>
        private string expr;

        /// <summary>
        /// 开始单词位置索引
        /// </summary>
        private int currentElementStartIndex;

        /// <summary>
        /// 下一单词开始位置索引
        /// </summary>
        private int nextElementStartIndex;

        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="exp">需要扫描的字符串</param>
        public ExpressionScanner(string exp)
        {
            this.expr = exp;
            this.currentElementStartIndex = 0;
            this.nextElementStartIndex = 0;
        }

        /// <summary>
        /// 获取当前单词
        /// </summary>
        public string CurrentElement
        {
            get
            {
                string ret = this.expr.Substring(this.currentElementStartIndex, this.nextElementStartIndex - this.currentElementStartIndex);
                ret = StringHelper.ReplaceSpaceChar(ret);
                return ret;
            }
        }

        /// <summary>
        /// 获取当前单词的前一字符
        /// </summary>
        public char PrevChar
        {
            get
            {
                if (this.currentElementStartIndex == 0)
                {
                    return char.MaxValue;
                }
                else
                {
                    int temp = this.currentElementStartIndex - 1;
                    while (temp > 0 && StringHelper.IsSpaceChar(this.expr[temp]))
                    {
                        temp -= 1;
                    }
                    return this.expr[temp];
                }
            }
        }

        /// <summary>
        /// 获取当前单词的后一字符
        /// </summary>
        public char NextChar
        {
            get
            {
                if (this.currentElementStartIndex == this.expr.Length - 1)
                {
                    return char.MaxValue;
                }
                else
                {
                    int temp = this.nextElementStartIndex;
                    while (temp < this.expr.Length - 1 && StringHelper.IsSpaceChar(this.expr[temp]))
                    {
                        temp += 1;
                    }
                    return this.expr[temp];
                }
            }
        }

        /// <summary>
        /// 移动扫描位置到下一单词
        /// </summary>
        /// <returns>是否已到达扫描字符串的结尾（true-未到结尾，false-已到达结尾）</returns>
        public bool MoveToNextElement()
        {
            bool ret = false;
            this.SkipSpace();
            char startChar = this.expr[this.currentElementStartIndex];
            bool startIsOperator = StringHelper.IsOperatorChar(startChar);
            bool startIsUnitaryOPerator = StringHelper.IsUnitaryOperatorChar(startChar);
            bool startSpecial = StringHelper.IsSpecialChar(startChar);
            bool hint = false;
            while (this.nextElementStartIndex < this.expr.Length - 1)
            {
                this.nextElementStartIndex++;
                char nextChar = this.expr[this.nextElementStartIndex];
                bool nextIsOperator = StringHelper.IsOperatorChar(nextChar);
                bool nextIsUnitaryOperator = StringHelper.IsUnitaryOperatorChar(nextChar);
                bool nextSpecial = StringHelper.IsSpecialChar(nextChar);
                if (!startSpecial && !startIsOperator && nextChar == '(')
                {
                    //处理函数的情况
                    this.nextElementStartIndex++;
                    ret = true;
                    hint = true;
                    break;
                }
                if (startSpecial || (!startSpecial && nextSpecial) || (!startIsOperator && nextIsOperator) || (startIsOperator && !nextIsOperator)
                    || (startIsOperator && !startIsUnitaryOPerator && nextIsUnitaryOperator))
                {
                    ret = true;
                    hint = true;
                    break;
                }
            }
            if (!hint)
            {
                //如果不是主动跳出循环，说明测试到了字符串末尾，则修正下一位置索引
                this.nextElementStartIndex++;
            }
            return ret;
        }

        /// <summary>
        /// 忽略扫描字符串的空白
        /// </summary>
        private void SkipSpace()
        {
            char temp = this.expr[this.nextElementStartIndex];
            while (StringHelper.IsSpaceChar(temp))
            {
                this.nextElementStartIndex++;
                temp = this.expr[this.nextElementStartIndex];
            }
            this.currentElementStartIndex = this.nextElementStartIndex;
        }
    }
}